﻿namespace AppLibrary.Storage
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel.Syndication;

    public class MemorySyndicationProvider : ISyndicationProvider
    {
        SyndicationFeed feed;

        Int32 nextItemId = 0;

        Dictionary<String, SyndicationItem> items = new Dictionary<String, SyndicationItem>();
        Dictionary<String, SyndicationCategory> categories = new Dictionary<String, SyndicationCategory>();
        Dictionary<String, SyndicationPerson> persons = new Dictionary<String, SyndicationPerson>();
        Dictionary<KeyValuePair<Uri, String>, SyndicationLink> links = new Dictionary<KeyValuePair<Uri, String>, SyndicationLink>();
        Dictionary<String, BinarySyndicationContent> content = new Dictionary<String, BinarySyndicationContent>();

        public MemorySyndicationProvider(SyndicationFeed feed)
        {
            this.feed = feed.Clone(false);
            this.feed.Items = null;

            LinkedList<SyndicationPerson> authors = new LinkedList<SyndicationPerson>();

            foreach (SyndicationPerson person in this.feed.Authors)
            {
                if (!this.persons.ContainsKey(person.Email))
                {
                    throw new MissingReferenceException(typeof(SyndicationFeed).GetProperty("Authors"));
                }
                else
                {
                    SyndicationPerson original = this.persons[person.Email];
                    if (original != person)
                    {
                        original = this.UpdatePerson(original.Email, person);
                    }

                    authors.AddLast(original);
                }
            }

            this.feed.Authors.Clear();
            

            foreach (SyndicationPerson person in this.feed.Contributors)
            {
                this.persons.Add(person.Email, person);
            }

            foreach (SyndicationCategory category in this.feed.Categories)
            {
                this.categories.Add(category.Name, category);
            }

            foreach (SyndicationLink link in this.feed.Links)
            {
                this.links.Add(new KeyValuePair<Uri, String>(link.Uri, link.RelationshipType), link);
            }
        }

        public IQueryable<SyndicationItem> Items
        {
            get { return this.items.Values.AsQueryable(); }
        }

        public IQueryable<SyndicationCategory> Categories
        {
            get { return this.categories.Values.AsQueryable(); }
        }

        public IQueryable<SyndicationPerson> Persons
        {
            get { return this.persons.Values.AsQueryable(); }
        }

        public IQueryable<SyndicationLink> Links
        {
            get { return this.links.Values.AsQueryable(); }
        }

        public IQueryable<BinarySyndicationContent> Content
        {
            get { return this.content.Values.AsQueryable(); }
        }

        public SyndicationFeed GetFeed(IEnumerable<SyndicationItem> items)
        {
            SyndicationFeed newFeed = this.feed.Clone(false);
            newFeed.Items = items;
            return newFeed;
        }

        public SyndicationFeed UpdateFeed(SyndicationFeed feedDetails)
        {
            this.feed = feed.Clone(false);
            this.feed.Items = null;

            foreach (SyndicationPerson person in this.feed.Authors)
            {
                if (this.persons.ContainsKey(person.Email))
                {
                    this.UpdatePerson(person.Email, person);
                }
                else
                {
                    this.persons.Add(person.Email, person);
                }
            }

            foreach (SyndicationPerson person in this.feed.Contributors)
            {
                if (this.persons.ContainsKey(person.Email))
                {
                    this.UpdatePerson(person.Email, person);
                }
                else
                {
                    this.persons.Add(person.Email, person);
                }
            }

            foreach (SyndicationCategory category in this.feed.Categories)
            {
                this.categories.Add(category.Name, category);
            }

            foreach (SyndicationLink link in this.feed.Links)
            {
                this.links.Add(new KeyValuePair<Uri, String>(link.Uri, link.RelationshipType), link);
            }

            return this.feed.Clone(false);
        }

        public SyndicationItem GetItem(String id)
        {
            return this.items[id];
        }

        public SyndicationItem CreateItem(SyndicationItem newItem)
        {
            throw new NotImplementedException();
        }

        public SyndicationItem UpdateItem(String id, SyndicationItem updatedItem)
        {
            throw new NotImplementedException();
        }

        public void DeleteItem(String id)
        {
            throw new NotImplementedException();
        }

        public SyndicationCategory GetCategory(String name)
        {
            throw new NotImplementedException();
        }

        public SyndicationCategory CreateCategory(SyndicationCategory newCategory)
        {
            throw new NotImplementedException();
        }

        public SyndicationCategory UpdateCategory(String originalName, SyndicationCategory updatedCategory)
        {
            throw new NotImplementedException();
        }

        public void DeleteCategory(String name)
        {
            throw new NotImplementedException();
        }

        public SyndicationPerson GetPerson(String email)
        {
            throw new NotImplementedException();
        }

        public SyndicationPerson CreatePerson(SyndicationPerson newPerson)
        {
            throw new NotImplementedException();
        }

        public SyndicationPerson UpdatePerson(String originalEmail, SyndicationPerson updatedPerson)
        {
            throw new NotImplementedException();
        }

        public void DeletePerson(String email)
        {
            throw new NotImplementedException();
        }

        public SyndicationLink GetLink(String uri, String relationship)
        {
            throw new NotImplementedException();
        }

        public SyndicationLink CreateLink(SyndicationLink newLink)
        {
            throw new NotImplementedException();
        }

        public SyndicationLink UpdateLink(String originalUri, String originalRelationship, SyndicationLink updatedLink)
        {
            throw new NotImplementedException();
        }

        public void DeleteLink(String uri, String relationship)
        {
            throw new NotImplementedException();
        }

        public BinarySyndicationContent GetContent(String id)
        {
            throw new NotImplementedException();
        }

        public BinarySyndicationContent CreateContent(BinarySyndicationContent newContent)
        {
            throw new NotImplementedException();
        }

        public BinarySyndicationContent UpdateContent(String id, BinarySyndicationContent updatedContent)
        {
            throw new NotImplementedException();
        }

        public void DeleteContent(String id)
        {
            throw new NotImplementedException();
        }
    }
}
